/**
 * @(#)AgBase1.java		
 * 
 * History:
 * 1.0	2 May 2012
 * 		Created
 * 1.1  7 May 2012
 * 	    Added 2 overridden methods to cater the message protocol: sendMessage and replyMessage
 * 2.0	12 May 2012
 * 		Added method for sending internal message (communication between agent in team 1 only)
 * 3.0	22 May 2012
 * 		Added method for replying message with a new action
 * 		Added method for replying internal message
 */
package upm.pb4agent.team1;

import jade.content.lang.Codec;
import jade.content.lang.Codec.CodecException;
import jade.content.lang.sl.SLCodec;
import jade.content.onto.Ontology;
import jade.content.onto.OntologyException;
import jade.content.onto.basic.Action;
import jade.core.AID;
import jade.core.Agent;
import jade.domain.DFService;
import jade.domain.FIPAException;
import jade.domain.FIPAAgentManagement.DFAgentDescription;
import jade.domain.FIPAAgentManagement.ServiceDescription;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
import jade.wrapper.AgentContainer;
import jade.wrapper.AgentController;
import jade.wrapper.StaleProxyException;
import upm.pb4agent.ontology.PB4AgentOntology;
import upm.pb4agent.team1.ontology.PB4AgentTeam1Ontology;

/**
 * This class is a base class that extends Agent class.
 * 
 * @version 3.0
 * @author Bob Nicolaus
 * 
 */
public class AgBase1 extends Agent {

	private static final long serialVersionUID = -9090015390921541805L;

	protected final Codec codec = new SLCodec();
	protected final Ontology ontology = PB4AgentOntology.getInstance();
	protected final Ontology team1Ontology = PB4AgentTeam1Ontology
			.getInstance();

	protected final MessageTemplate standardTemplate = MessageTemplate.and(
			MessageTemplate.MatchLanguage(codec.getName()),
			MessageTemplate.MatchOntology(ontology.getName()));

	protected final MessageTemplate standardInternalTemplate = MessageTemplate
			.and(MessageTemplate.MatchLanguage(codec.getName()),
					MessageTemplate.MatchOntology(team1Ontology.getName()));

	protected AgBase1() {
		super();

		getContentManager().registerLanguage(codec);
		getContentManager().registerOntology(ontology);
		getContentManager().registerOntology(team1Ontology);
	}

	/**
	 * This method handles the creation of a new agent.
	 * 
	 * @param nickname
	 *            the name given for the new agent
	 * @param className
	 *            the class of the new agent
	 * @param args
	 *            the parameter to be passed to the new agent constructor
	 * @throws StaleProxyException
	 */
	protected void createNewAgent(String nickname, String className,
			Object[] args) throws StaleProxyException {

		AgentContainer agentContainer = getContainerController();
		AgentController agentController = agentContainer.createNewAgent(
				nickname, className, args);
		agentController.start();
	}

	/**
	 * This method handles the agent registration to the DF.
	 * 
	 * @param type
	 *            the agent type
	 * @throws FIPAException
	 */
	protected void registerAgent(String type) throws FIPAException {
		DFAgentDescription dfd = new DFAgentDescription();
		ServiceDescription sd = new ServiceDescription();
		sd.setName(getName());
		sd.setType(type);
		dfd.addServices(sd);
		DFService.register(this, dfd);
		dfd = null;
		sd = null;

		System.out.println(type + " is registered in the DF");

		doWait(1000);
	}

	/**
	 * Sends message to an agent.
	 * 
	 * @param performative
	 *            The message performative
	 * @param receiver
	 *            The agent that will receive the message
	 */
	protected void sendMessage(int performative, AID receiver) {
		ACLMessage aclMessage = new ACLMessage(performative);

		aclMessage.setLanguage(codec.getName());
		aclMessage.setOntology(ontology.getName());
		aclMessage.addReceiver(receiver);

		send(aclMessage);
		//System.out.println(aclMessage);
	}

	/**
	 * Sends message to an agent.
	 * 
	 * @param performative
	 *            The message performative
	 * @param receiver
	 *            The agent that will receive the message
	 * @param action
	 *            The content of the message
	 * @param protocol
	 *            The protocol of the message
	 * @throws OntologyException
	 * @throws CodecException
	 */
	protected void sendMessage(int performative, AID receiver, Action action,
			String protocol) throws CodecException, OntologyException {
		ACLMessage aclMessage = new ACLMessage(performative);

		aclMessage.setLanguage(codec.getName());
		aclMessage.setOntology(ontology.getName());
		aclMessage.addReceiver(receiver);
		aclMessage.setProtocol(protocol);

		getContentManager().fillContent(aclMessage, action);

		send(aclMessage);
		//System.out.println(aclMessage);
	}

	/**
	 * Sends message to an internal agent.
	 * 
	 * @param performative
	 *            The message performative
	 * @param receiver
	 *            The agent that will receive the message
	 * @param action
	 *            The content of the message
	 * @param protocol
	 *            The protocol of the message
	 * @throws OntologyException
	 * @throws CodecException
	 */
	protected void sendInternalMessage(int performative, AID receiver,
			Action action, String protocol) throws CodecException,
			OntologyException {
		ACLMessage aclMessage = new ACLMessage(performative);

		aclMessage.setLanguage(codec.getName());
		aclMessage.setOntology(team1Ontology.getName());
		aclMessage.addReceiver(receiver);
		aclMessage.setProtocol(protocol);

		getContentManager().fillContent(aclMessage, action);

		send(aclMessage);
	}

	/**
	 * Replies the original message.
	 * 
	 * @param message
	 *            The original message
	 * @param performative
	 *            The reply message performative
	 * @param protocol
	 *            The protocol of the message
	 */
	protected void replyMessage(ACLMessage message, int performative,
			String protocol) {
		ACLMessage reply = message.createReply();

		reply.setLanguage(codec.getName());
		reply.setOntology(ontology.getName());
		reply.setPerformative(performative);
		reply.setProtocol(protocol);

		send(reply);
	}

	/**
	 * Replies the original message internally.
	 * 
	 * @param message
	 *            The original message
	 * @param performative
	 *            The reply message performative
	 * @param protocol
	 *            The protocol of the message
	 */
	protected void replyInternalMessage(ACLMessage message, int performative,
			String protocol) {
		ACLMessage reply = message.createReply();

		reply.setLanguage(codec.getName());
		reply.setOntology(team1Ontology.getName());
		reply.setPerformative(performative);
		reply.setProtocol(protocol);

		send(reply);
	}

	/**
	 * Replies the original message with a new action.
	 * 
	 * @param message
	 *            The original message
	 * @param performative
	 *            The reply message performative
	 * @param action
	 *            The new action of the reply
	 * @param protocol
	 *            The protocol of the message
	 * @throws CodecException
	 * @throws OntologyException
	 */
	protected void replyMessage(ACLMessage message, int performative,
			Action action, String protocol) throws CodecException,
			OntologyException {
		ACLMessage reply = message.createReply();

		reply.setLanguage(codec.getName());
		reply.setOntology(ontology.getName());
		reply.setPerformative(performative);
		reply.setProtocol(protocol);

		getContentManager().fillContent(reply, action);

		send(reply);
	}
}
